package com.ruoyi.generator;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import org.apache.calcite.adapter.jdbc.JdbcSchema;
import org.apache.calcite.jdbc.CalciteConnection;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.RelRoot;
import org.apache.calcite.rel.RelWriter;
import org.apache.calcite.rel.externalize.RelWriterImpl;
import org.apache.calcite.schema.Schema;
import org.apache.calcite.schema.SchemaPlus;
import org.apache.calcite.sql.SqlExplainLevel;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.dialect.MysqlSqlDialect;
import org.apache.calcite.sql.parser.SqlParser;
import org.apache.calcite.tools.FrameworkConfig;
import org.apache.calcite.tools.Frameworks;
import org.apache.calcite.tools.Planner;
import org.springframework.core.io.ClassPathResource;


import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.sql.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;

public class MultiSource {
    public static void main(String[] args) throws Exception {
        ClassPathResource classPathResource = new ClassPathResource("multiSource.json");
//        String filepath = "E:\\work_space\\毕业设计\\代码生成器\\RuoYi\\ruoyi-generator\\src\\main\\resources\\multiSource.json";
        Properties config = new Properties();
        config.put("caseSensitive" , "false");

        Connection connection = DriverManager.getConnection("jdbc:calcite:" , config);

        CalciteConnection calciteConnection = connection.unwrap(CalciteConnection.class);

        SchemaPlus rootSchema = calciteConnection.getRootSchema();
        ObjectMapper jackson = new ObjectMapper();
        HashMap map = jackson.readValue(classPathResource.getInputStream(), HashMap.class);

        List<Map> schemas = (List<Map>) map.get("schemas");

        for (Map schema : schemas) {
            String name = schema.get("name").toString();
            Schema schema1 = JdbcSchema.create(rootSchema, name, (Map<String, Object>) schema.get("operand"));
            rootSchema.add(name, schema1);
        }

        String sql = "SELECT * FROM mssql.sys_user ";


        try (Statement stmt = calciteConnection.createStatement()) {
            try (ResultSet rs = stmt.executeQuery(sql)) {
                //打印逻辑计划
                printLogicPlan(classPathResource.getFile().getAbsolutePath(), sql);
                //打印查询结果
                printRs(rs);
            }
        }


    }

    public static void printRs(ResultSet rs) throws Exception {
        ResultSetMetaData rsmd = rs.getMetaData();
        int count = rsmd.getColumnCount();
        System.out.println();

        while (rs.next()) {
            for (int i = 1; i <= count; i++) {
                System.out.print(rs.getString(i) + "\t");
            }
            System.out.println();
        }
    }

    public static void printLogicPlan(String modelPath, String sql) throws Exception {

        String modelJsonStr = Files.readAllLines(Paths.get(modelPath)).stream().collect(Collectors.joining("\n"));
        ObjectMapper jackson = new ObjectMapper();
        HashMap map = jackson.readValue(modelJsonStr, HashMap.class);

        List<Map> schemas = (List<Map>) map.get("schemas");

        SchemaPlus rootSchema = Frameworks.createRootSchema(true);

        for (Map schema : schemas) {
            String name = schema.get("name").toString();
            Schema schema1 = JdbcSchema.create(rootSchema, name, (Map<String, Object>) schema.get("operand"));
            rootSchema.add(name, schema1);
        }
        SqlParser.Config insensitiveParser = SqlParser.configBuilder()
                .setCaseSensitive(false)
                .build();

        FrameworkConfig config = Frameworks.newConfigBuilder()
                .parserConfig(insensitiveParser)
                .defaultSchema(rootSchema)
                .build();

        Planner planner = Frameworks.getPlanner(config);
        SqlNode sqlNode = planner.parse(sql);
        SqlNode sqlNodeValidated = planner.validate(sqlNode);
        RelRoot relRoot = planner.rel(sqlNodeValidated);
        RelNode relNode = relRoot.project();
    }
}
